<template>
  <div class="container">
    <header>
      <h1>404</h1>
      <div class="subtitle">简单、快速、安全的局域网</div>
    </header>

    <div class="status-bar">
      <div>
        <strong>状态:</strong>
        <span v-if="isConnect" class="status-connected"
          >已连接到服务器 ({{ wsUrl }})</span
        >
        <span v-else class="status-disconnected">未连接</span>
      </div>
      <div style="width: 300px; display: flex; justify-content: space-around">
        <el-input
          v-model="wsUrl"
          size="small"
          :disabled="isConnect"
          placeholder="输入服务器地址"
        />
        <el-button type="primary" size="small" @click="connectWebSocket">{{
          isConnect ? "断开" : "连接"
        }}</el-button>
      </div>
    </div>

    <div class="main-content">
      <div class="panel user-panel">
        <h2 class="panel-title"><i>👥</i> 在线用户</h2>
        <ul class="user-list">
          <li
            v-for="(user, index) in onlineUsers"
            :key="user.id"
            class="user-item"
            :class="{ active: selectedUser && selectedUser === user }"
            @click="selectUser(user)"
          >
            <div class="user-avatar">用户</div>
            <div class="user-info">
              <div class="user-name">用户{{ index + 1 }}</div>
              <div class="user-ip">{{ user }}</div>
            </div>
          </li>
        </ul>
      </div>

      <div class="panel main-panel">
        <h2 class="panel-title"><i>🫵</i> 对话</h2>
        <div class="chatBox">
          <div class="msgCard" v-for="item in msgList" :key="item.id">
            <div class="tooltips" v-if="item.type === '0'">
              {{ item.time }} {{ item.message }}
            </div>
            <div class="userMsg" v-else>
              <!-- 去掉日期保留时间 -->
              <{{ item.time.slice(10) }}>
              <span class="address">"{{ item.ip }}"</span> ：
              <span class="msg">{{ item.message }}</span>
            </div>
          </div>
        </div>
        <div class="sendBox">
          <el-input
            v-model="sendMsg"
            :rows="2"
            type="textarea"
            placeholder="输入消息"
            @keydown.enter="sendMessage"
          />
          <el-button type="primary" size="small" @click="sendMessage"
            >发送</el-button
          >
          <input
            type="file"
            ref="fileInput"
            style="display: none"
            @change="handleFileSelect"
          />
          <el-button
            type="success"
            size="small"
            @click="$refs.fileInput.click()"
            >发送文件</el-button
          >
        </div>
      </div>
    </div>
  </div>
  <el-dialog
    v-model="dialogVisible"
    title="🫵通知"
    width="500"
    :before-close="handleClose"
  >
    <span>收到一份文件，是否下载</span>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="downloadFile"> 下载 </el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup>
import { ref, watch, nextTick, onMounted } from "vue";
import { ElMessage } from "element-plus";

const dialogVisible = ref(false);
const socket = ref(null);
const isConnect = ref(false);
const wsUrl = ref("192.168.100.118:9957");
const sendMsg = ref("");
const selectedUser = ref(null);

const msgList = ref([]);
const onlineUsers = ref([]);
// 新增响应式数据
const fileInput = ref(null);
const selectedFile = ref(null);

const fileReceived = ref(null);
const selectUser = (user) => {
  selectedUser.value = user;
};
const connectWebSocket = () => {
  if (isConnect.value) {
    socket.value?.close();
    isConnect.value = false;
  } else {
    try {
      socket.value = new WebSocket("ws://" + wsUrl.value);
    } catch (error) {
      ElMessage.error({ message: "连接失败，检查服务器地址！", duration: 800 });
    }
    socket.value.onopen = function (event) {
      ElMessage.success({ message: "服务器已连接！", duration: 800 });
      isConnect.value = true;
    };

    socket.value.onerror = function (error) {
      ElMessage.error({ message: "连接出错！", duration: 800 });
    };

    socket.value.onmessage = function (event) {
      let data = JSON.parse(event.data);
      if (data.type === "all") {
        msgList.value = data.messages;
        onlineUsers.value = data.ips;
      }
      if (data.type === "file") {
        dialogVisible.value = true;
        console.log("data", data);
        fileReceived.value = {
          id: Date.now(),
          type: "file",
          sender: data.sender,
          fileName: data.fileName,
          fileType: data.fileType,
          fileData: data.fileData,
          time: getCurrentTime(),
        };
      }
    };

    socket.value.onclose = function () {
      ElMessage.error({ message: "服务器已断开！", duration: 800 });
      isConnect.value = false;
    };
  }
};
const sendMessage = () => {
  if (socket.value && socket.value.readyState === WebSocket.OPEN) {
    let obj = {
      type: "message",
      msg: sendMsg.value,
      time: getCurrentTime(),
    };
    socket.value.send(JSON.stringify(obj));
    sendMsg.value = "";
  } else {
    ElMessage.error({ message: "未连接服务器！", duration: 800 });
  }
};
function getCurrentTime() {
  const now = new Date();
  const date = [
    now.getFullYear(),
    (now.getMonth() + 1).toString().padStart(2, "0"),
    now.getDate().toString().padStart(2, "0"),
  ].join("/"); // 修改这里，使用斜杠 '/' 连接日期

  const time = [
    now.getHours().toString().padStart(2, "0"),
    now.getMinutes().toString().padStart(2, "0"),
    now.getSeconds().toString().padStart(2, "0"),
  ].join(":");

  return `${date} ${time}`;
}

// 监听menuList变化，输出111
// 使用Vue的nextTick来确保DOM更新后再执行滚动操作
watch(msgList, (newValue) => {
  nextTick(() => {
    let ele = document.querySelector(".chatBox");
    if (ele) {
      ele.scrollTop = ele.scrollHeight - ele.clientHeight;
    }
  });
});

// 文件选择处理
const handleFileSelect = (e) => {
  selectedFile.value = e.target.files[0];
  if (selectedFile.value) {
    sendFile(selectedFile.value);
  }
  e.target.value = ""; // 重置input
};

// 文件发送方法
const sendFile = (file) => {
  if (!selectedUser.value) {
    ElMessage.warning("请先选择接收用户");
    return;
  }

  const reader = new FileReader();
  reader.onload = () => {
    const fileData = reader.result.split(",")[1]; // 获取Base64数据

    if (socket.value?.readyState === WebSocket.OPEN) {
      socket.value.send(
        JSON.stringify({
          type: "file",
          msg: JSON.stringify({
            target: selectedUser.value,
            fileName: file.name,
            fileType: file.type,
            fileData,
          }),
        })
      );

      // 本地显示发送记录
      msgList.value.push({
        id: Date.now(),
        type: "file",
        sender: "我",
        fileName: file.name,
        time: getCurrentTime(),
      });
    }
  };
  reader.readAsDataURL(file);
};

// 文件下载方法
const downloadFile = () => {
  let item = fileReceived.value;
  const link = document.createElement("a");
  link.href = `data:${item.fileType};base64,${item.fileData}`;
  link.download = item.fileName;
  link.click();
  dialogVisible.value = false;
};
const initCursor = () => {
  let body = document.getElementsByClassName("container")[0];
  let arr = [
    "富强",
    "民主",
    "文明",
    "和谐",
    "自由",
    "平等",
    "公正",
    "法制",
    "爱国",
    "敬业",
    "诚信",
    "友善",
  ];
  let index = 0;
  var text = document.createElement("div");
  body.addEventListener("click", (e) => {
    var x = e.pageX;
    var y = e.pageY;
    text.setAttribute("class", "floatingfont");
    body.appendChild(text);
    text.style.left = x - text.clientWidth / 2 + "px";
    text.style.top = y - text.clientHeight / 2 + "px";
    text.style.color = getRandomColor();
    // text.style.cursor = `url("./assets/cursor.png"),default`;
    text.innerHTML = arr[index];
    index == arr.length - 1 ? (index = 0) : index++;
  });
  document.documentElement.addEventListener("animationend", function (e) {
    text.parentNode.removeChild(text);
  });
};

const getRandomColor = () => {
  return (
    "#" +
    (function (h) {
      return new Array(7 - h.length).join("0") + h;
    })(((Math.random() * 0x1000000) << 0).toString(16))
  );
};
onMounted(() => {
  initCursor();
});
</script>
<style lang="less">
.container {
  width: 100vw;
  height: 100%;
  background: linear-gradient(135deg, #bdc3c7,#2c3e50, #bdc3c7);
  background-size: 400% 400%;
  animation: gradientBG 15s ease infinite;
  color: #fff;
  min-height: 100vh;
  padding: 20px;
  cursor: url("./assets/cursor.png"), default;
  position: relative;
  .floatingfont {
    position: absolute;
    z-index: 99;
    animation: float 1.5s;
    color: rgb(223, 66, 66);
    font-size: 18px;
    font-weight: 600;
    // cursor: default;
    cursor: url("./assets/cursor.png"), default;
    user-select: none;
  }
}

@keyframes gradientBG {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
@keyframes float {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0.6;
  }
  100% {
    opacity: 0;
    transform: translateY(-100px);
  }
}
header {
  text-align: center;
  margin-bottom: 20px;
  padding: 10px;
  background: rgba(0, 0, 0, 0.3);
  border-radius: 15px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(10px);
}
h1 {
  font-size: 2rem;
  margin-bottom: 10px;
  color: #fff;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}

.subtitle {
  font-size: 1.2rem;
  opacity: 0.8;
  margin-bottom: 20px;
}
.status-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: rgba(0, 0, 0, 0.4);
  padding: 10px 20px;
  border-radius: 10px;
  margin-bottom: 20px;
}
.status-connected {
  margin-left: 5px;
  color: #4ade80;
}
.status-disconnected {
  margin-left: 5px;
  color: #f87171;
}
.main-content {
  display: flex;
  gap: 20px;
  margin-bottom: 30px;
}

.panel {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 15px;
  padding: 20px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(10px);
  flex: 1;
}

.user-panel {
  flex: 0 0 300px;
}

.main-panel {
  flex: 2;
}
.panel-title {
  font-size: 1.5rem;
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 2px solid rgba(255, 255, 255, 0.2);
  display: flex;
  align-items: center;
}

.panel-title i {
  margin-right: 10px;
  color: #4dabf7;
}

.user-list {
  list-style: none;
}

.user-item {
  padding: 12px 15px;
  margin: 10px 0;
  background: rgba(0, 0, 0, 0.3);
  border-radius: 10px;
  display: flex;
  align-items: center;
  transition: all 0.3s ease;
  cursor: pointer;
}

.user-item:hover {
  background: rgba(77, 171, 247, 0.3);
  transform: translateX(5px);
}

.user-item.active {
  background: rgba(77, 171, 247, 0.5);
  border-left: 4px solid #4dabf7;
}

.user-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #4dabf7;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 15px;
  font-weight: bold;
  font-size: 15px;
}
.chatBox {
  height: 500px;
  padding: 0 10px;
  overflow-y: scroll;
  overflow-x: hidden;

  &::-webkit-scrollbar {
    height: 5px;
    width: 5px;
  }

  &::-webkit-scrollbar-thumb {
    border-radius: 5px;
    background: #858585;
  }

  &::-webkit-scrollbar-track {
    border-radius: 5px;
    background: #f0f0f0;
  }

  .msgCard {
    color: #333;
    font-size: 12px;
    margin-bottom: 5px;
    width: 100%;

    .tooltips {
      width: 100%;
      color: #4dabf7;
      text-align: center;
      font-size: 14px;
    }

    .userMsg {
      width: 100%;
      display: flex;
      padding: 0 0 0 5px;
      font-size: 16px;
      color: #4dabf7;
      border-radius: 5px;
      box-shadow: 0 0 5px #fff;
      opacity: 0.8;
      .address {
        font-weight: 700;
        color: #4dabf7;
      }
      .msg {
        margin-left: 5px;
        // background: #999;
        flex: 1;
        -webkit-user-select: text;
        color: #fff;
        text-align: start;
        /* 自动换行增强 */
        white-space: pre-wrap; // 保留空格/换行符
        word-break: break-all; // 强制断开长英文字符串（无论是否合理）
        overflow-wrap: break-word;
      }
    }
  }
}
.sendBox {
  -webkit-app-region: no-drag;
  width: 100%;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: space-between;

  .el-input {
    margin: 0 5px;
    flex: 1;
  }
  .el-button {
    margin: 0 2px;
    height: 100%;
  }
}
</style>
